package com.awol2010ex.logback.appender.redis.stream;


import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Layout;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import com.awol2010ex.logback.appender.common.JSONEventLayout;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.*;

import java.time.Duration;
import java.util.Map;

public class RedisStreamAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {

    JedisPool pool;

    // keep this for config compatibility for now
    JSONEventLayout jsonlayout;

    Layout<ILoggingEvent> layout;

    // logger configurable options
    private String host = "localhost";
    private int port = Protocol.DEFAULT_PORT;
    private String key = null;
    private int timeout = Protocol.DEFAULT_TIMEOUT;
    private String password = null;
    private int database = Protocol.DEFAULT_DATABASE;
    private int timeBetweenEvictionRuns = 30000; //default in JedisPoolConfig
    private int minEvictableIdleTime = 60000; //default in JedisPoolConfig

    public RedisStreamAppender() {
        jsonlayout = new JSONEventLayout();
    }

    @Override
    protected void append(ILoggingEvent event) {
        Jedis client = pool.getResource();
        try {
            Map<String,String> json = jsonlayout.doLayout(event);

            client.xadd(key, StreamEntryID.NEW_ENTRY,json);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (client != null) {
                client.close();
            }
        }
    }


    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getDatabase() {
        return database;
    }

    public void setDatabase(int database) {
        this.database = database;
    }


    public Layout<ILoggingEvent> getLayout() {
        return layout;
    }

    public void setLayout(Layout<ILoggingEvent> layout) {
        this.layout = layout;
    }

    public int getTimeBetweenEvictionRuns() {
        return timeBetweenEvictionRuns;
    }

    public void setTimeBetweenEvictionRuns(int timeBetweenEvictionRuns) {
        this.timeBetweenEvictionRuns = timeBetweenEvictionRuns;
    }

    public int getMinEvictableIdleTime() {
        return minEvictableIdleTime;
    }

    public void setMinEvictableIdleTime(int minEvictableIdleTime) {
        this.minEvictableIdleTime = minEvictableIdleTime;
    }

    @Override
    public void start() {
        super.start();
        GenericObjectPoolConfig config = new JedisPoolConfig();
        config.setTestOnBorrow(true);
        config.setTimeBetweenEvictionRuns(Duration.ofMillis(timeBetweenEvictionRuns));
        config.setMinEvictableIdleTime(Duration.ofMillis(minEvictableIdleTime));
        pool = new JedisPool(config, host, port, timeout, password, database);
    }

    @Override
    public void stop() {
        super.stop();
        pool.destroy();
    }

}

